//
#include "MotorInit.h"
//
/**
  * @brief  Configures the different system clocks.
  * @param  None
  * @retval None
  */
void RCC_Configuration(void)
{
    /* initialize Delay Function */
    Delay_init();

    /* ADCCLK = PCLK2/6 = 120M/6 = 20M*/
    RCC_ADCCLKConfig(RCC_APB2CLK_Div6);

    /* UART2,TMR3,TMR6,TMR14 clocks enable */
    RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_USART2 | RCC_APB1PERIPH_TMR3 |RCC_APB1PERIPH_TMR6 | RCC_APB1PERIPH_TMR14, ENABLE);
    
    /* TMR1,TMR15,ADC1 clocks enable */
    RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_ADC1 | RCC_APB2PERIPH_TMR1 | RCC_APB2PERIPH_SYSCFGCOMP, ENABLE);
    
    /* GPIOA,GPIOB,GPIOC,GPIOF,DMA1 clocks enable */
    RCC_AHBPeriphClockCmd(RCC_AHBPERIPH_GPIOA | RCC_AHBPERIPH_GPIOB | RCC_AHBPERIPH_GPIOC | RCC_AHBPERIPH_GPIOF 
                        | RCC_AHBPERIPH_FLASH | RCC_AHBPERIPH_DMA1, ENABLE);
}

/**
  * @brief  Configures NVIC and Vector Table base location.
  * @param  None
  * @retval None
  */
void NVIC_Configuration(void)
{
	NVIC_InitType NVIC_InitStructure = {0};
    //
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    //
    #if OCP_HW_EN
    /* Configure and enable TMR1_BRK interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                      = TMR1_BRK_UP_TRG_COM_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* Configure and enable TMR3 interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                      = TMR3_GLOBAL_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* Configure and enable ADC interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                      = ADC_COMP_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    /* Configure and enable TIM6 interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                      = TMR6_GLOBAL_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 3;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    #else
    /* Configure and enable TMR3 interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                      = TMR3_GLOBAL_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* Configure and enable ADC interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                      = ADC_COMP_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    /* Configure and enable TIM6 interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                      = TMR6_GLOBAL_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    #endif
}

/******************************************************************************
//!\brief	The GPIO module initialization  
//!\param	None
//!\retval  None
******************************************************************************/
void GPIO_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure = {0};
    //
    /*LED and Debug:Configure PA15 PB8 PB11 as ouput port and push-pull*/
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pins = GPIO_Pins_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OutType = GPIO_OutType_PP;
    GPIO_InitStructure.GPIO_Pull = GPIO_Pull_NOPULL;
    GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    //
    GPIO_InitStructure.GPIO_Pins = GPIO_Pins_9| GPIO_Pins_8 | GPIO_Pins_11;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    //
    LED1_ON;
    LED2_ON;
    LED3_ON;
    //*Key1 and Key2:Configure PA11 PA12 as input port*/
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pins = GPIO_Pins_11 | GPIO_Pins_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_OutType = GPIO_OutType_PP;
    GPIO_InitStructure.GPIO_Pull = GPIO_Pull_PU;
    GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_2MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /*ACP_GPIO,FWR and Hall:Configure PB4 PB5 PB6 PB7 as input port*/
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pins = GPIO_Pins_3 | GPIO_Pins_4 | GPIO_Pins_5 | GPIO_Pins_6 | GPIO_Pins_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_OutType = GPIO_OutType_PP;
    GPIO_InitStructure.GPIO_Pull = GPIO_Pull_PU;
    GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_2MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    /*ADC:Configure PA4 PA5 PA6 PA7 PB0 PB1 PB2 as alternate function*/
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pins = GPIO_Pins_4 | GPIO_Pins_5 |GPIO_Pins_6 | GPIO_Pins_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    //
    GPIO_InitStructure.GPIO_Pins = GPIO_Pins_0 | GPIO_Pins_1 |GPIO_Pins_2;
    GPIO_Init(GPIOB, &GPIO_InitStructure); 

    /*PWM: Configure PA8 PA9 PA10 PB13 PB14 PB15 as alternate function*/
    GPIO_PinAFConfig(GPIOA, GPIO_PinsSource8, GPIO_AF_2);
    GPIO_PinAFConfig(GPIOA, GPIO_PinsSource9, GPIO_AF_2);
    GPIO_PinAFConfig(GPIOA, GPIO_PinsSource10, GPIO_AF_2);
    //
    GPIO_PinAFConfig(GPIOB, GPIO_PinsSource13, GPIO_AF_2);
    GPIO_PinAFConfig(GPIOB, GPIO_PinsSource14, GPIO_AF_2);
    GPIO_PinAFConfig(GPIOB, GPIO_PinsSource15, GPIO_AF_2);

    /*BKIN: Configure PB12 as alternate function*/
    #if OCP_HW_EN
    GPIO_PinAFConfig(GPIOB, GPIO_PinsSource12, GPIO_AF_2);
    #endif
    
    /*Configure PA8 PA9 PA10 as alternate function mode and pull down*/
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pins = GPIO_Pins_8 | GPIO_Pins_9 | GPIO_Pins_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
    GPIO_InitStructure.GPIO_Pull = GPIO_Pull_PD;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /*Configure PB12 PB13 PB14 PB15 as alternate function mode and pull down*/
    #if OCP_HW_EN
    GPIO_InitStructure.GPIO_Pins = GPIO_Pins_12 | GPIO_Pins_13 | GPIO_Pins_14 | GPIO_Pins_15;
    #else
    GPIO_InitStructure.GPIO_Pins = GPIO_Pins_13 | GPIO_Pins_14 | GPIO_Pins_15;
    #endif
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/*****************************************************************************
//!\brief	The ADC module initialization  
//!\param	None
//!\retval  None
*****************************************************************************/
void ADC_Configuration(void)
{
    ADC_InitType  ADC_InitStructure = {0};
    DMA_InitType  DMA_InitStructure = {0};
    //
    /* Configure the DMA channels remapping */
    SYSCFG_DMAChannelRemapConfig(SYSCFG_DMARemap_ADC1,DISABLE);
    /* DMA1 Channel1 Configuration ----------------------------------------------*/
    DMA_Reset(DMA1_Channel1);
    DMA_DefaultInitParaConfig(&DMA_InitStructure);
    DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t)&ADC1->RDOR;
    DMA_InitStructure.DMA_MemoryBaseAddr        = (uint32_t)g_ADC_RegularConvertedValueTab;
    DMA_InitStructure.DMA_Direction             = DMA_DIR_PERIPHERALSRC;
    DMA_InitStructure.DMA_BufferSize            = 3;
    DMA_InitStructure.DMA_PeripheralInc         = DMA_PERIPHERALINC_DISABLE;
    DMA_InitStructure.DMA_MemoryInc             = DMA_MEMORYINC_ENABLE;
    DMA_InitStructure.DMA_PeripheralDataWidth   = DMA_PERIPHERALDATAWIDTH_HALFWORD;
    DMA_InitStructure.DMA_MemoryDataWidth       = DMA_MEMORYDATAWIDTH_HALFWORD;
    DMA_InitStructure.DMA_Mode                  = DMA_MODE_CIRCULAR;
    DMA_InitStructure.DMA_Priority              = DMA_PRIORITY_HIGH;
    DMA_InitStructure.DMA_MTOM                  = DMA_MEMTOMEM_DISABLE;
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);

    /* Enable DMA1 channel1 */
    DMA_ChannelEnable(DMA1_Channel1, ENABLE);

    /* ADC1 Configuration ------------------------------------------------------*/
    ADC_StructInit(&ADC_InitStructure);
    ADC_InitStructure.ADC_Mode                  = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanMode              = ENABLE;
    ADC_InitStructure.ADC_ContinuousMode        = DISABLE;
    ADC_InitStructure.ADC_ExternalTrig          = ADC_ExternalTrig_None;
    ADC_InitStructure.ADC_DataAlign             = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NumOfChannel          = 3;
    ADC_Init(ADC1, &ADC_InitStructure);

    /* ADC1 regular channel configuration */ 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_7_5);  // AD_OTP
    ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SampleTime_7_5);  // AD_SPEED
    ADC_RegularChannelConfig(ADC1, ADC_Channel_10,3, ADC_SampleTime_7_5);  // AD_VM
    /* Set injected sequencer length */
    ADC_InjectedSequencerLengthConfig(ADC1, 1);
    /* ADC1 injected channel Configuration */ 
    ADC_InjectedChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_7_5);  // AD_IBUS

    /* ADC1 injected external trigger configuration */
    ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjec_TMR1_CC4);

    /* Enable automatic injected conversion start after regular one */
    ADC_AutoInjectedConvCtrl(ADC1, DISABLE);

    /* Enable ADC1 DMA */
    ADC_DMACtrl(ADC1, ENABLE);

    /* Enable ADC1 external trigger */ 
    ADC_ExternalTrigConvCtrl(ADC1, ENABLE);
    ADC_ExternalTrigInjectedConvCtrl(ADC1,ENABLE);

    /* Enable JEOC interrupt */
    ADC_INTConfig(ADC1, ADC_INT_JEC, ENABLE);

    /* Enable ADC1 */
    ADC_Ctrl(ADC1, ENABLE);

    /* Enable ADC1 reset calibration register */   
    ADC_RstCalibration(ADC1);

    /* Check the end of ADC1 reset calibration register */
    while(ADC_GetResetCalibrationStatus(ADC1));

    /* Start ADC1 calibration */
    ADC_StartCalibration(ADC1);
    /* Check the end of ADC1 calibration */
    while(ADC_GetCalibrationStatus(ADC1));
}

/*****************************************************************************
//!\brief	The Timer 1 module initialization  
//!\param	None
//!\retval  None
*****************************************************************************/
void TIM1_Configuration(void)
{
    TMR_TimerBaseInitType   TMR_TimeBaseStructure= {0};
    TMR_OCInitType          TMR_OCInitStructure= {0};
    TMR_BRKDTInitType       TMR_BRKDTInitStructure= {0};
    //
    g_MotorPolePairs = MOTOR_POLE_PAIRS;
    g_PWM_Frequency = PWM_FREQUENCY;
    g_PWM_Period = ((1000000 * 1000) / g_PWM_Frequency);                  // unit:1 ns
    g_PWMLoadData = (((SystemCoreClock / g_PWM_Frequency)/2) - 1);
    //
    /* TMR1  TMR3 Configuration */
    /* Time Base configuration */
    TMR_TimeBaseStructInit(&TMR_TimeBaseStructure);
    TMR_TimeBaseStructure.TMR_DIV = 0x0000;
    TMR_TimeBaseStructure.TMR_CounterMode = TMR_CounterDIR_CenterAligned3;
    TMR_TimeBaseStructure.TMR_Period = g_PWMLoadData;
    TMR_TimeBaseStructure.TMR_ClockDivision = TMR_CKD_DIV1;
    TMR_TimeBaseStructure.TMR_RepetitionCounter = 0x0000;
    TMR_TimeBaseInit(TMR1, &TMR_TimeBaseStructure);
    TMR_TimeBaseInit(TMR3, &TMR_TimeBaseStructure);
    
    /* Channel 1, 2,3 and 4 Configuration in PWM mode */
    TMR_OCStructInit(&TMR_OCInitStructure);
    TMR_OCInitStructure.TMR_OCMode = TMR_OCMode_PWM1;
    TMR_OCInitStructure.TMR_OutputState = TMR_OutputState_Disable;
    TMR_OCInitStructure.TMR_OutputNState = TMR_OutputNState_Disable;
    TMR_OCInitStructure.TMR_Pulse = 0;
    TMR_OCInitStructure.TMR_OCPolarity = TMR_OCPolarity_High;
    TMR_OCInitStructure.TMR_OCNPolarity = TMR_OCNPolarity_High;
    TMR_OCInitStructure.TMR_OCIdleState = TMR_OCIdleState_Reset;
    TMR_OCInitStructure.TMR_OCNIdleState = TMR_OCNIdleState_Reset;
    // TMR1_CC1
    TMR_OC1Init(TMR1, &TMR_OCInitStructure);
    // TMR1_CC2
    TMR_OC2Init(TMR1, &TMR_OCInitStructure);
    // TMR1_CC3
    TMR_OC3Init(TMR1, &TMR_OCInitStructure);
    // TMR3_CC1
    TMR_OC1Init(TMR3, &TMR_OCInitStructure);
    // TMR3_CC2
    TMR_OC2Init(TMR3, &TMR_OCInitStructure);
    
    // TMR1_CC4
    TMR_OCInitStructure.TMR_Pulse = 1;
    TMR_OCInitStructure.TMR_OCPolarity = TMR_OCPolarity_Low;
    TMR_OCInitStructure.TMR_OCNPolarity = TMR_OCNPolarity_Low;
    TMR_OCInitStructure.TMR_OutputState = TMR_OutputState_Enable;
    TMR_OC4Init(TMR1, &TMR_OCInitStructure);
    // TMR3_CC4
    TMR_OCInitStructure.TMR_Pulse = (g_PWMLoadData - 1);
    TMR_OC4Init(TMR3, &TMR_OCInitStructure);
    //
    TMR_OC1PreloadConfig(TMR1,TMR_OCPreload_Enable);
    TMR_OC2PreloadConfig(TMR1,TMR_OCPreload_Enable);
    TMR_OC3PreloadConfig(TMR1,TMR_OCPreload_Enable);
    TMR_OC4PreloadConfig(TMR1,TMR_OCPreload_Enable);
    TMR_OC4PreloadConfig(TMR3,TMR_OCPreload_Enable);
    // Master Mode selection: TMR1
    TMR_SelectMasterSlaveMode(TMR1, TMR_MasterSlaveMode_Enable);
    TMR_SelectOutputTrigger(TMR1, TMR_TRGOSource_Enable);
    
    // Slave Mode selection: TMR3
    TMR_SelectSlaveMode(TMR3, TMR_SlaveMode_Gate);
    TMR_SelectInputTrigger(TMR3, TMR_TRGSEL_ITR0);

    // Brake configuration
    TMR_BRKDTStructInit(&TMR_BRKDTInitStructure);
    TMR_BRKDTInitStructure.TMR_OSIMRState = TMR_OSIMRState_Disable;
    TMR_BRKDTInitStructure.TMR_OSIMIState = TMR_OSIMIState_Disable;
    TMR_BRKDTInitStructure.TMR_LOCKgrade = TMR_LOCKgrade_OFF;
    TMR_BRKDTInitStructure.TMR_DeadTime = PWM_DEAD_TIME;
    //
    #if OCP_HW_EN
    TMR_BRKDTInitStructure.TMR_Break = TMR_Break_Enable;
    #else
    TMR_BRKDTInitStructure.TMR_Break = TMR_Break_Disable;
    #endif
    //
    TMR_BRKDTInitStructure.TMR_BreakPolarity = TMR_BreakPolarity_High;
    TMR_BRKDTInitStructure.TMR_AutomaticOutput = TMR_AutomaticOutput_Disable;
    TMR_BRKDTConfig(TMR1,&TMR_BRKDTInitStructure);
    //
    #if OCP_HW_EN
    TMR_INTConfig(TMR1,TMR_INT_Break,ENABLE);
    #else
    TMR_INTConfig(TMR1,TMR_INT_Break,DISABLE);
    #endif
    // TMR3 CC1,CC2 disable
    TMR_INTConfig(TMR3,TMR_INT_CC1,DISABLE);
    TMR_INTConfig(TMR3,TMR_INT_CC2,DISABLE);
    // TMR1 TMR3  counter  enable
    TMR_Cmd(TMR3, ENABLE);
    TMR_Cmd(TMR1, ENABLE);
    // TMR1 TMR3  Main Output enable
    TMR_CtrlPWMOutputs(TMR3, ENABLE);
    TMR_CtrlPWMOutputs(TMR1, ENABLE);
}

/*****************************************************************************
//!\brief	The Timer 6 module initialization. T = 250us.
//!\param	None
//!\retval  None
*****************************************************************************/
void TIM6_Configuration(void)
{TMR_TimerBaseInitType   TMR_TimeBaseStructure= {0};
uLONG freq_1 = 0,freq_2 = 0;
//
    freq_1 = 1000000;           // T = 1/freq_1 = 1/1000000 = 1us
    freq_2 = 20000;             // T = 1/freq_2 = 1/20000  = 50us
    /* Time Base configuration */
    TMR_TimeBaseStructInit(&TMR_TimeBaseStructure);
    TMR_TimeBaseStructure.TMR_DIV = ((SystemCoreClock / freq_1) - 1);
    TMR_TimeBaseStructure.TMR_CounterMode = TMR_CounterDIR_Up;
    TMR_TimeBaseStructure.TMR_Period = ((freq_1 / freq_2) - 1);
    TMR_TimeBaseStructure.TMR_ClockDivision = TMR_CKD_DIV1;
    TMR_TimeBaseStructure.TMR_RepetitionCounter = 0x0000;
    TMR_TimeBaseInit(TMR6, &TMR_TimeBaseStructure);
    //
    TMR_INTConfig(TMR6,TMR_INT_Overflow,ENABLE);
    /* TMR6 counter enable */
    TMR_Cmd(TMR6, ENABLE);
}

/*****************************************************************************
//!\brief	The MCU DEBUG initialization  
//!\param	None
//!\retval  None
*****************************************************************************/
void MCUDBU_Configuration(void)
{    
    MCUDBG_PeriphDebugModeConfig(MCUDBG_SLEEP,ENABLE);
    MCUDBG_PeriphDebugModeConfig(MCUDBG_STOP,ENABLE);
    MCUDBG_PeriphDebugModeConfig(MCUDBG_STANDBY,ENABLE);
    //
    MCUDBG_PeriphDebugModeConfig(MCUDBG_IWDG_STOP,ENABLE);
    MCUDBG_PeriphDebugModeConfig(MCUDBG_WWDG_STOP,ENABLE);
    //
    MCUDBG_PeriphDebugModeConfig(MCUDBG_I2C1_SMBUS_TIMEOUT,ENABLE);
    MCUDBG_PeriphDebugModeConfig(MCUDBG_I2C2_SMBUS_TIMEOUT,ENABLE);
    //
    MCUDBG_PeriphDebugModeConfig(MCUDBG_ERTC_STOP,ENABLE);
    MCUDBG_PeriphDebugModeConfig(MCUDBG_ERTC_512_STOP,ENABLE);
    //
    MCUDBG_PeriphDebugModeConfig(MCUDBG_TMR1_STOP,ENABLE);
    MCUDBG_PeriphDebugModeConfig(MCUDBG_TMR3_STOP,ENABLE);
    MCUDBG_PeriphDebugModeConfig(MCUDBG_TMR6_STOP,ENABLE);
    MCUDBG_PeriphDebugModeConfig(MCUDBG_TMR15_STOP,ENABLE);
    MCUDBG_PeriphDebugModeConfig(MCUDBG_TMR16_STOP,ENABLE);
    MCUDBG_PeriphDebugModeConfig(MCUDBG_TMR17_STOP,ENABLE);
    MCUDBG_PeriphDebugModeConfig(MCUDBG_TMR14_STOP,ENABLE);
}

/*****************************************************************************
//!\brief	The IWDG initialization  
//!\param	None
//!\retval  None
*****************************************************************************/
void IWDG_Configuration(void)
{
    /* Enable write access to IWDG_PSC and IWDG_RLD registers */
    IWDG_KeyRegWrite(IWDG_KeyRegWrite_Enable);
    /* IWDG counter clock: LSI/16 */
    IWDG_SetPrescaler(IWDG_Psc_16);

    /* Set counter reload value to obtain 30ms IWDG TMReOut
     Counter Reload Value = 30ms/IWDG counter clock period
                          = 30ms / (16/LSI)
                          = 0.03s / (16/LsiFreq)
                          = (3 * LsiFreq)/(16 * 100)
                          = (3 * LsiFreq)/1600
    */
    IWDG_SetReload((3 * 40000) / 1600);
    /* Reload IWDG counter */
    IWDG_ReloadCounter();
    /* Enable IWDG (the LSI oscillator will be enabled by hardware) */
    IWDG_Enable();
}

//=========================================================================================

